using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

namespace Nirvana
{
    [CustomEditor(typeof(BigWorld))]
    public class BigWorldInspector : Editor
    {
        private BigWorld _bigWorld;
        private static Action _onSerializeCallback;

        private void OnEnable()
        {
            _bigWorld = target as BigWorld;
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("保存"))
            {
                Export();
            }

            EditorGUILayout.EndHorizontal();
        }

        /// <summary>
        /// 导出数据
        /// </summary>
        private void Export()
        {
            if (string.IsNullOrEmpty(_bigWorld.fileName))
            {
                Debug.LogError("请配置导出场景的ID!!!");
                SerializeCallback();
                return;
            }

            CollectSceneData();
        }

        private void CollectSceneData()
        {
            SceneData data = new SceneData();
            List<SerializedGameObject> objects = new List<SerializedGameObject>();
            for (int i = 0; i < _bigWorld.transform.childCount; i++)
            {
                Transform child = _bigWorld.transform.GetChild(i);
                if (!child.gameObject.activeSelf) continue;
                SerializedGameObject node = new SerializedGameObject();
                node.NodeToDeserialize(-1, child, ObjectType.Node);
                objects.Add(node);
                FindObject(child, objects.Count - 1, objects);
            }

            data.Objects = objects.ToArray();
            data.ResourcePaths = BigWorldEditorUtility.GetPaths().ToArray();
            SaveData(data);
        }

        private void FindObject(Transform parent, int parentId, List<SerializedGameObject> objects)
        {
            for (int i = 0; i < parent.childCount; i++)
            {
                Transform child = parent.GetChild(i);
                if (!child.gameObject.activeSelf) continue;
                if (child.name.EndsWith("(Missing Prefab)"))
                {
                    Debug.LogError($"Mission Prefab: {child.name}");
                    continue;
                }

                ObjectType type;
                SerializedGameObject node;
                if (BigWorldEditorUtility.IsMesh(child, out int matPathId, out int meshPathId))
                {
                    type = ObjectType.Mesh;
                    SerializedMesh meshData = new SerializedMesh();
                    MeshRenderer renderer = child.GetComponent<MeshRenderer>();
                    meshData.MatPathId = matPathId;
                    meshData.MeshPathId = meshPathId;
                    meshData.Radius = Mathf.Max(renderer.bounds.size.x, renderer.bounds.size.y, renderer.bounds.size.z) / 2;
                    meshData.Center = renderer.bounds.center;
                    meshData.CollectData(renderer);
                    node = meshData;
                }
                else
                {
                    type = ObjectType.Node;
                    node = new SerializedGameObject();
                }

                node.NodeToDeserialize(parentId, child, type);
                objects.Add(node);
                if (type == ObjectType.Node)
                {
                    FindObject(child, objects.Count - 1, objects);
                }
            }
        }

        private void SaveData(SceneData data)
        {
            string sceneName = _bigWorld.fileName;
            string filePath = $"Assets/BigWorld/Resources/Scene/Data/SceneData_{sceneName}.bytes";
            data.SerializeToFile(filePath);

            // 好家伙，还能这么测试数据？
            SceneData test = new SceneData();
            test.Deserialize(File.ReadAllBytes(filePath));
            test.SerializeToFile(filePath);

            AssetDatabase.Refresh();

            SerializeCallback();
        }

        private void SerializeCallback()
        {
            Action action = _onSerializeCallback;
            _onSerializeCallback = null;
            action?.Invoke();
        }
    }
}